# 3. yarn.lock、package-lock.json、npm-shrinkwrap.json的理解
# 1. 先说下yarn下载包的流程
第一次,首先执行yarn install
,会按照语义版本控制规则(在下面会解释)下载最新的依赖包并且构建为依赖关系树,也就是把共有的部分提取出来。然后生成yarn.lock
文件。并且生成本地缓存。
以后执行yarn install
会先对比package.json
版本号和yarn.lock
版本号是否一致。分两种情况:
(1)如果不一致会根据package中的版本号以及语义版本控制规则去下载最新的包,并更新至yarn.lock
。
(2)如果一致,会根据lock查看缓存进行复制,没有缓存就按照路径下载,注意:这里不会理会package实际包的版本是否有更新。这个比如删除node_moudles
后再执行yarn install
会复制缓存,而不是重新下载,同时也会根据yarn.lock
文件中依赖的相互关系生成依赖树,版本也和package中的相同。
npm5中是 如果改了package.json
,且package.json
和package-lock.json
文件中包版本号不一致,那么执行npm i
时npm会根据package中的版本号以及语义含义去下载最新的包,并更新至lock。如果两者是同一状态,那么执行npm i
都会根据lock下载,不会理会package实际包的版本是否有新。和yarn是一样的。
# 2. npm-shrinkwrap.json 与 package-lock.json的区别与联系
# 从npm版本看
package-lock.json
是npm5的新特性,也不向前兼容,如果npm版本是4或以下,那得用npm-shrinkwrap.json
# 从npm处理机制来看
- 在一个项目里,如果本身不存在这两个文件,那么在运行
npm install
时,会自动生成一个package-lock.json
,或者在初始化一个项目npm init
时,也会生成package-lock.json
,安装信息会依据该文件进行,而不是单纯按照package.json
,这两个文件的优先级都比package.json
高 - 如果项目两个文件都存在,那么安装的依赖是依据
npm-shrinkwrap.json
来的,而忽略package-lock.json
- 运行命令
npm shrinkwrap
后,如果项目里不存在package-lock.json,那么会新建一个npm-shrinkwrap.json
文件,如果存在package-lock.json
,那么会把package-lock.json
重命名为npm-shrinkwrap.json
# 从文件更新来看
npm-shrinkwrap.json
只会在运行npm shrinkwrap
才会创建/更新
package-lock.json
会在修改pacakge.json
或者node_modules
时就会自动产生或更新了。
# 从发布包来看
package-lock.json
不会在发布包中出现,就算出现了,也会遭到npm的无视。
npm-shrinkwrap.json
可以在发布包中出现
# 3. 解释与实践
项目package.json
中包版本号前如果有^ ~
之类的会按照语义版本控制规则 (opens new window)(也可以看下这个博客https://blog.csdn.net/ZQ_KING/article/details/81560075 (opens new window))安装规则下最高版本的包(只限定于没有lock文件时候。如果有lock文件会根据lock文件中的下载路径下载,当然你可以在有lock文件情况下yarn upgrade vue
,就会按照语义规则下最高版本的包下载)。但是package.json
中的对应包的版本号没变,只改变了yarn.lock
中对应包的部分信息和node_moudles
中的对应包。
比如拿vue这个包来说,现在最高版本号是2.6.10
,我package.json
文件中版本号是^2.6.6
,当yarn install
时,它会下载>=2.6.6
<3.0.0
间最大的就是2.6.10
版本号的vue包(只限定于没有lock文件)。它会先更新node_moudles
然后更新yarn.lock
中vue包内容。下载完成后package.json
中vue版本号还是vue : ^2.6.6
,更新yarn.lock
文件中vue包的详细信息。
实际上node_moudles
中下载的是2.6.10
版本的。所以说提不提交yarn.lock
到代码托管平台是有争议的,因为提交了可能依赖会有地雷,不提交依赖关系可能会出错,一般来说是应该提交的。可以看这个(为什么我不使用 shrinkwrap(lock) (opens new window))
# 4. yarn.lock文件的作用(自己理解的,如有错误请指出)
yarn.lock
是为了维护树关系,保证依赖间的相互关系,和包的下载路径。如果改了package.json
版本号,且package.json
和lock文件版本号不同,那么执行yarn install
时,会根据package中的版本号以及语义含义去下载最新的包,并更新至lock。这也是yarn.lock
提交到代码托管平台的原因。因为安装依赖时会按照lock中下载路径走,并且不需要重新生成依赖关系树了,其他机器yarn install
时包间依赖关系和版本就不会出现的错误。npm中npm install
有可能会因为包间的版本不同导致版本和依赖错误(除非有package.lock.json文件)。
总的来说yarn.lock
和package-lock.json
起的作用相同。只不过yarn是默认的,npm到5以后才会出现lock。两者确定包间的依赖关系算法也不同,总之yarn就是为了弥补npm的缺陷而出现的。
# 5. 相关链接
yarn:
https://yarn.bootcss.com/docs/dependency-versions/ (opens new window)(版本范围规则)
https://yarn.bootcss.com/blog/2016/11/24/lockfiles-for-all/ (opens new window)(yarn.lock文件应该提交到托管平台上)
https://yarn.bootcss.com/docs/yarn-lock/ (opens new window)(yarn.lock文件解释)
npm:
https://www.zhihu.com/question/264560841 (opens new window)(package-lock.json 需要写进 .gitignore 吗?)
https://juejin.im/post/5c53bea8e51d457fbe226efb (opens new window)(对npm包精准控制之npm-shrinkwrap.json与package-lock.json)
https://zhuanlan.zhihu.com/p/22934066 (opens new window)(为什么我不使用 shrinkwrap(lock))
夜里因为这个睡不着,导致第二天还睡过头了只能请假。最后,觉得有帮助的点个赞o~~